package com.yixq.soa.service.web.service;

import com.yixq.soa.service.comm.utils.DateUtils;
import com.yixq.soa.service.web.annotation.DataValid;
import com.yixq.soa.service.web.em.RegexType;
import com.yixq.soa.service.web.fieldvalidator.ValidatorFactory;
import com.yixq.soa.service.web.utils.RegexUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.List;

/**
 * Created by marvin on 2017/2/15.
 */
public class DataValidService {

    private static DataValid dataValid;

    public DataValidService() {
        super();
    }

    public static String checkData(Object object) {
        String result = null;
        try {
            if (object.getClass().isPrimitive()) {
                return null;
            }

            if (List.class.isAssignableFrom(object.getClass())) {
                for (Object args : (List) object) {
                    DataValidService.valid(args);
                }
            } else {
                DataValidService.valid(object);
            }
        } catch (Exception e) {
            if(StringUtils.isNotBlank(e.getMessage())){//放开在方法中可空的参数cameraBrandList(String brandName）
                result = "参数校验失败：" + e.getMessage();
            }
        }
        return result;
    }

    //解析的入口
    public static void valid(Object object) throws Exception{
        //获取object的类型
        Class<? extends Object> clazz=object.getClass();
        //获取该类型声明的成员
        Field[] fields=clazz.getDeclaredFields();
        //遍历属性
        for(Field field:fields){
            //对于private私有化的成员变量，通过setAccessible来修改器访问权限
            field.setAccessible(true);
            validate(field,object);
            //重新设置会私有权限
            field.setAccessible(false);
        }
    }


    public static void validate(Field field,Object object) throws Exception{

        String description;
        Object value;

        //获取对象的成员的注解信息
        dataValid=field.getAnnotation(DataValid.class);
        value=field.get(object);

        if(dataValid==null)return;

        description=dataValid.description().equals("")?field.getName():dataValid.description();


        /*************注解解析工作开始******************/
        if(!dataValid.nullable()){
            if(value==null|| StringUtils.isBlank(value.toString())){
                throw new Exception(description+"不能为空");
            }
            if(value.toString().length()>dataValid.maxLength()&&dataValid.maxLength()!=0){
                throw new Exception(description+"长度不能超过"+dataValid.maxLength());
            }

            if(value.toString().length()<dataValid.minLength()&&dataValid.minLength()!=0){
                throw new Exception(description+"长度不能小于"+dataValid.minLength());
            }
        }else if(dataValid.nullable()){//可空，有值时先判断长度
            if(value!=null && !StringUtils.isBlank(value.toString())){
                if(value.toString().length()>dataValid.maxLength()&&dataValid.maxLength()!=0){
                    throw new Exception(description+"长度不能超过"+dataValid.maxLength());
                }

                if(value.toString().length()<dataValid.minLength()&&dataValid.minLength()!=0){
                    throw new Exception(description+"长度不能小于"+dataValid.minLength());
                }
            }
        }

        String checkmsg = ValidatorFactory.checkField(dataValid, object, value);
        if (StringUtils.isNotEmpty(checkmsg)) {
            throw new Exception(String.format("%s%s", description, checkmsg));
        }
      
        boolean nullFlag = dataValid.nullable();
        if(dataValid.regexType()!= RegexType.NONE){
            switch (dataValid.regexType()) {
                case NONE:
                    break;
                case NO_SPECIALCHAR:
                    if(!nullFlag && RegexUtils.hasSpecialChar(value.toString())){
                        throw new Exception(description+"不能含有特殊字符");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){//非必填且不为空
                        if(RegexUtils.hasSpecialChar(value.toString())){
                            throw new Exception(description+"不能含有特殊字符");
                        }
                    }
                    break;
                case IS_GUID:
                    if(!nullFlag && !RegexUtils.isGuid(value.toString())){
                        throw new Exception(description+"不能含有特殊字符");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){
                        if(!RegexUtils.isGuid(value.toString())){
                            throw new Exception(description+"不能含有特殊字符");
                        }
                    }
                    break;
                case PASSWORD18:
                    if(!nullFlag && !RegexUtils.isPassword18(value.toString())){
                        throw new Exception(description+"密码必须6-18位的字母和数字");
                    }
                    break;
                case CHINESE:
                    if(!nullFlag && !RegexUtils.isChinese2(value.toString())){
                        throw new Exception(description+"不是中文字符");
                    }
                    break;
                case EMAIL:
                    if(!nullFlag && !RegexUtils.isEmail(value.toString())){
                        throw new Exception(description+"地址格式不正确");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){
                        if(!RegexUtils.isEmail(value.toString())){
                            throw new Exception(description+"地址格式不正确");
                        }
                    }
                    break;
                case IP:
                    if(!nullFlag && !RegexUtils.isIp(value.toString())){
                        throw new Exception(description+"地址格式不正确");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){
                        if(!RegexUtils.isIp(value.toString())){
                            throw new Exception(description+"地址格式不正确");
                        }
                    }
                    break;
                case DATE_YYYY_MM_DD:
                	if(!nullFlag && !RegexUtils.isDateForYyyyMmDd(value.toString())){
                		throw new Exception(description+"格式不正确");
                	}else if(nullFlag && RegexUtils.isNotNull(value)){
                		if(!RegexUtils.isDateForYyyyMmDd(value.toString())){
                			throw new Exception(description+"格式不正确");
                		}
                	}
                	break;
                case DATE_YYYY_MM_DD_HH_MM_SS:
                	if(!nullFlag && !DateUtils.isValidDate(value.toString())){
                		throw new Exception(description+"格式不正确");
                	}else if(nullFlag && RegexUtils.isNotNull(value)){
                		if(!DateUtils.isValidDate(value.toString())){
                			throw new Exception(description+"格式不正确");
                		}
                	}
                	break;
                case ID:
                    if(!nullFlag && !RegexUtils.isIdcard(value.toString())){
                        throw new Exception(description+"格式不正确");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){
                        if(!RegexUtils.isIdcard(value.toString())){
                            throw new Exception(description+"格式不正确");
                        }
                    }
                    break;
                case NUMBER:
                    if(!nullFlag && !RegexUtils.isNumber(value.toString())){
                        throw new Exception(description+"不是数字");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){
                        if(!RegexUtils.isNumber(value.toString())){
                            throw new Exception(description+"不是数字");
                        }
                    }
                    break;
                case DECIMAL:
                	if(null!=value){
                		try{
                    		Double.valueOf(value.toString());
                    	}catch(Exception e){
                    		 throw new Exception(description+"不是小数");
                    	}
            		}
                    break;
                case MOBILE:
                    if(!nullFlag && !RegexUtils.isMobile(value.toString())){
                        throw new Exception(description+"格式不正确");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){
                        if(!RegexUtils.isMobile(value.toString())){
                            throw new Exception(description+"格式不正确");
                        }
                    }
                    break;
                case ALL_MOBILE:
                	if(!nullFlag && !RegexUtils.isAllMobile(value.toString())){
                		throw new Exception(description+"格式不正确");
                	}else if(nullFlag && RegexUtils.isNotNull(value)){
                		if(!RegexUtils.isAllMobile(value.toString())){
                			throw new Exception(description+"格式不正确");
                		}
                	}
                	break;
                case MOBILE_TEL:
                    if(!nullFlag && !RegexUtils.isMoibleOrTelePhone(value.toString())){
                        throw new Exception(description+"格式不正确");
                    }else if(nullFlag && RegexUtils.isNotNull(value)){
                        if(!RegexUtils.isMoibleOrTelePhone(value.toString())){
                            throw new Exception(description+"格式不正确");
                        }
                    }
                    break;
                default:
                    break;
            }
        }

        if(!dataValid.regexExpression().equals("")){
            if(value.toString().matches(dataValid.regexExpression())){
                throw new Exception(description+"格式不正确");
            }
        }
        /*************注解解析工作结束******************/
    }
}
